(load 'lisp_translate)
(load 'operadores)
(load 'evaluar)

(defun RUN
	(PRG ENT &optional (MEM nil))
	(IF (NULL PRG) NIL
		(IF (EQ (CAAR PRG) 'int) (RUN (CDR PRG) ENT (AGREGARMEMORIA (CDAR PRG) MEM))
			(IF (EQ (CAAR PRG) 'main) (EJECT (CADAR PRG) ENT MEM) 
				'error
			)
		)
	)
)

(defun EJECT (PRG ENT MEM &optional (SAL NIL))
	(IF (NULL PRG) (REVERSE SAL)
		(COND
			( (EQ (CAAR PRG) 'scanf)  (ejecutar_scanf  prg mem ent sal))
			( (EQ (CAAR PRG) 'printf) (ejecutar_printf prg mem ent sal))
			( (ESASIGNACION (CAR PRG) MEM) (EJECT (CDR PRG) ENT (ASIGNACION (CAR PRG) MEM) SAL) )
			( (EQ (CAAR PRG) 'if) (ejecutar_if prg mem ent sal))
			( (EQ (CAAR PRG) 'while) (ejecutar_while prg mem ent sal))
			( (EQ (CAAR PRG) 'for) (ejecutar_for prg mem ent sal))
		)
	)
)

;-----------------------------------------------------------------------
; Aca separamos la logica de algunas de las cosas que ejecuta EJECT
;

(defun ejecutar_scanf (prg mem ent sal)
	(EJECT (CDR PRG) (CDR ENT) (MODIFMEM (CADAR PRG) (CAR ENT) MEM) SAL)
)

(defun ejecutar_printf (prg mem ent sal)
	(EJECT (CDR PRG) ENT MEM (CONS (evaluar (CADAR PRG) MEM) SAL)) 
)

(defun ejecutar_if (prg mem ent sal)
	(IF (NOT (EQ (evaluar (CADAR PRG) MEM) 0))
					(EJECT (APPEND (NTH 2 (CAR PRG)) (CDR PRG)) ENT MEM SAL)
					(IF (EQ (LENGTH (CAR PRG)) 5)
						(EJECT (APPEND (NTH 4 (CAR PRG)) (CDR PRG)) ENT MEM SAL)
						(EJECT (CDR PRG) ENT MEM SAL)
					)
	)
)

(defun ejecutar_while (prg mem ent sal)
	(IF (EQ (evaluar (CADAR PRG) MEM) 0) (EJECT (CDR PRG) ENT MEM SAL)
		(EJECT (APPEND (NTH 2 (CAR PRG)) PRG) ENT MEM SAL)
	)
)

(defun ejecutar_for (prg mem ent sal)
	(IF (EQ (length (CADAR PRG)) 3)
		(EJECT
			(APPEND 
				(LIST (CAADAR PRG)) 
				(APPEND 
					(LIST 
						(LIST (CAAR PRG) 
							(LIST (NTH 1 (CADAR PRG)) (NTH 2 (CADAR PRG))
							)
							(NTH 2 (CAR PRG)) 
						) 			
					) 
					(CDR PRG)
				) 
			)
		ENT MEM SAL)
		
		(IF (EQ (evaluar (CAADAR PRG) MEM) 0) (EJECT (CDR PRG) ENT MEM SAL)
			(EJECT (APPEND (NTH 2 (CAR PRG)) (LIST (NTH 1 (CADAR PRG))) PRG ) ENT MEM SAL)
		)
	)
)

;-----------------------------------------------------------------------

(defun ESASIGNACION (L MEM)
	(IF (ESVARIABLE (CAR L) MEM) T
		(OR (EQ (CAR L) '++) (EQ (CAR L) '--))
	)
)

(defun ESVARIABLE (A MEM)
	(NOT (NULL (BUSCAR A MEM)))
)


(defun ASIGNACION (L MEM)
	(IF (ESVARIABLE (CAR L) MEM)
		(COND
			( (EQ (NTH 1 L) '=) (MODIFMEM (CAR L) (evaluar (NTH 2 L) MEM) MEM) )
			( (EQ (NTH 1 L) '++) (ASIGNACION (LIST (CAR L) '= (LIST (CAR L) '+ 1)) MEM) )
			( (EQ (NTH 1 L) '--) (ASIGNACION (LIST (CAR L) '= (LIST (CAR L) '- 1)) MEM) )
			( (EQ (NTH 1 L) '+=) (ASIGNACION (LIST (CAR L) '= (LIST (CAR L) '+ (CADDR L))) MEM) )
			( (EQ (NTH 1 L) '-=) (ASIGNACION (LIST (CAR L) '= (LIST (CAR L) '- (CADDR L))) MEM) )
			( T (ASIGNACION (LIST (CAR L) '= (CAR L) (NTH 1 L) (NTH 3 L)) MEM) )
		)
		(ASIGNACION (REVERSE L) MEM)
	)
)


(defun AGREGARMEMORIA (L MEM)
	(IF (NULL L) MEM		
		(AGREGARMEMORIA (CDR L) (APPEND (LIST (CAR L) '= '0) MEM))
	
	)
)

(defun BUSCAR (A M)
	(IF (NULL M) NIL
		(IF (EQ A (CAR M)) (CADDR M)
			(BUSCAR A (CDDDR M))
		)
	)
)

(defun MODIFMEM (A V M &optional (OUT NIL))
	(IF (NULL M) OUT
		(IF (EQ A (CAR M)) (APPEND OUT (list (CAR m) (CADR m) V) (CDDDR M) )
			(MODIFMEM A V (CDDDR M) (APPEND OUT (list (CAR m) (CADR m) (CADDR m))) )
		)
	)
)

